#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char const* argv[])
{
    int fd;
    struct flock lock;

    if (argc != 2)
    {
        printf("usage : %s <filename>\n", argv[0]);
        exit(0);
    }

    if ((fd = open(argv[1], O_RDWR)) < 0)
    {
        perror("open error");
        exit(0);
    }

    lock.l_type = F_WRLCK;
    lock.l_start = 0;
    lock.l_whence = SEEK_SET;
    lock.l_len = 100;
    lock.l_pid = getpid();
    if (fcntl(fd, F_GETLK, &lock) < 0)
    {
        perror("fcntl error");
        exit(0);
    }

    if (lock.l_type == F_UNLCK)
        printf("unlock now\n");
    else
        printf("locked????\n");

    lock.l_type = F_WRLCK;
    if (fcntl(fd, F_SETLK, &lock) < 0)
    {
        perror("fcntl error");
        exit(0);
    }

    if (fork() == 0)
    {
        lock.l_pid = getpid();
        if (fcntl(fd, F_GETLK, &lock) < 0)
        {
            perror("fcntl error");
            exit(0);
        }

        if (lock.l_type == F_UNLCK)
            printf("unlock now\n");
        else if (lock.l_type == F_WRLCK)
            printf("write lock\n");
        else printf("read lock\n");

        exit(0);
    }
    else
    {
        lock.l_type = F_RDLCK;
        lock.l_start = 50;
        if (fcntl(fd, F_SETLK, &lock) < 0)
        {
            perror("fcntl error");
            exit(0);
        }

        if (fork() == 0)
        {
            lock.l_type = F_WRLCK;
            lock.l_start = 0;
            lock.l_len = 50;
            lock.l_pid = getpid();
            if (fcntl(fd, F_GETLK, &lock) < 0)
            {
                perror("fcntl error");
                exit(0);
            }
            
            printf("at 0~49: ");

            if (lock.l_type == F_UNLCK)
                printf("unlock now\n");
            else if (lock.l_type == F_WRLCK)
                printf("write lock\n");
            else printf("read lock\n");

            lock.l_type = F_WRLCK;
            lock.l_start = 50;
            lock.l_len = 50;
            lock.l_pid = getpid();
            if (fcntl(fd, F_GETLK, &lock) < 0)
            {
                perror("fcntl error");
                exit(0);
            }
            
            printf("at 50~99: ");

            if (lock.l_type == F_UNLCK)
                printf("unlock now\n");
            else if (lock.l_type == F_WRLCK)
                printf("write lock\n");
            else printf("read lock\n");
            
            lock.l_type = F_WRLCK;
            lock.l_start = 100;
            lock.l_len = 50;
            lock.l_pid = getpid();
            if (fcntl(fd, F_GETLK, &lock) < 0)
            {
                perror("fcntl error");
                exit(0);
            }
            
            printf("at 100~149: ");

            if (lock.l_type == F_UNLCK)
                printf("unlock now\n");
            else if (lock.l_type == F_WRLCK)
                printf("write lock\n");
            else printf("read lock\n");

            exit(0);
        }
        
        wait(NULL);
    }

    return 0;
}
